'use strict'

const { Service } = require('ee-core')
const fs = require('fs-extra')
const path = require('path')
const os = require('os')
const exec = require("child_process").exec
// 获取桌面路径
const desktopDir = path.join(os.homedir(), 'Desktop')
// 获取当前日期并格式化为 YYYY-MM-DD
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0') // 月份从 0 开始，需要加 1
const day = String(today.getDate()).padStart(2, '0')
const folderName = `${year}-${month}-${day}前端发版文件`
const baseDir = path.join(desktopDir, folderName)
const listFile = "list.txt"
class AsyncQueue {
    queue = [];
    runningTasks = 0;
    constructor(maxLength = 10, retryLimit = 3) {
        this.maxLength = maxLength
        this.retryLimit = retryLimit
    }

    async enqueue (asyncFunction) {
        return new Promise(async (resolve, reject) => {
            const task = { asyncFunction, retries: 0, resolve, reject }

            this.queue.push(task)

            if (this.runningTasks >= this.maxLength) {
                return
            }
            // 启动异步任务
            this.processQueue()
        })
    }

    async processQueue () {
        if (!this.queue.length || this.runningTasks >= this.maxLength) {
            return
        }
        const tasksToProcess = this.queue.splice(0, this.maxLength - this.runningTasks)
        this.runningTasks += tasksToProcess.length

        await Promise.all(
            tasksToProcess.map(async ({ asyncFunction, retries, resolve, reject }) => {
                try {
                    const result = await asyncFunction()
                    resolve(result)
                } catch (error) {
                    if (retries < this.retryLimit) {
                        this.queue.push({ asyncFunction, retries: retries + 1, resolve, reject })
                    } else {
                        reject(error)
                    }
                } finally {
                    this.runningTasks--
                }
            })
        )
        await this.processQueue()
    }
}
/**
 * 示例服务（service层为单例）
 * @class
 */
class FsService extends Service {

    constructor(ctx) {
        super(ctx)
    }

    /**
     * test
     */
    async getFile (args) {
        try {
            const copyQueue = new AsyncQueue(10)
            const showLimit = 5
            let showResultList = []
            const originPathSource = []
            let { username, startTime, endTime, repoPath } = args
            const outputPath = path.resolve(process.cwd(), baseDir)
            const listFilePath = path.resolve(outputPath, listFile)
            if (!username) {
                username = await execCmd("git config --get user.name")
            }
            const authorParams = username === "*" ? "" : `--author="${username}" `
            const copyFileHandle = async (skip = 0, maxCount = 10) => {
                /* 获取原来的文件列表 */
                const originList = loadFile(listFilePath).split(/[\r\n]/g)
                    .map(el => el.trim())
                    .filter(el => el.length !== 0)

                // 使用 --git-dir 和 --work-tree 指定 Git 仓库路径
                let pathList = await execCmd(
                    `git --git-dir="${path.join(repoPath, '.git')}" --work-tree="${repoPath}" log --name-only --pretty=format: ${authorParams}--after="${startTime}" --before="${endTime}" --skip=${skip} --max-count=${maxCount}`
                )
                /* 新提取的文件列表 */
                pathList = pathList.split(/[\r\n]/g)
                    .map(el => el.trim())
                    .filter(el => el.length !== 0)

                if (!pathList.length) {
                    return
                }

                const newFileList = [...new Set(pathList)]
                /* 并发模式拷贝文件 */
                const copyPromiseList = newFileList.map(item => {
                    return copyQueue.enqueue(async () => {
                        const filePath = item.trim()
                        if (filePath.length === 0) {
                            return
                        }
                        // 文件来源地址
                        originPathSource.push(path.resolve(repoPath, filePath))
                        await copyFile(filePath, repoPath)
                    })
                })
                await Promise.all(copyPromiseList)

                /* 所有的文件列表 */
                writeFile(listFilePath, [...new Set(originList.concat(newFileList))].join("\r\n"))

                /* 用于显示提取结果的列表 */
                showResultList = [...new Set(showResultList.concat(newFileList))]

                await copyFileHandle(skip + maxCount, maxCount)
            }
            await copyFileHandle()
            const resultSize = showResultList.length
            if (resultSize > showLimit) {
                showResultList = showResultList.slice(0, showLimit)
                showResultList.push("...", `请前往 ${listFilePath} 查看全部提取文件列表`)
            }
            const res = {
                successful: true,
                resultSize,
                username,
                startTime,
                endTime,
                outputPath,
                repoPath,
                showResultList,
                originPathSource
            }
            return res
        } catch (error) {
            console.log(error)
            return {
                successful: false,
                error
            }
        }
    }
    async getGitUserName (args) {
        const username = await execCmd("git config --get user.name")
        return username
    }

}
function execCmd (command) {
    return new Promise((resolve, reject) => {
        exec(command, (error, stdout) => {
            if (error) {
                return reject(error)
            }
            resolve(stdout.toString().trim())
        })
    })
}
function loadFile (filePath) {
    try {
        return fs.readFileSync(filePath, "utf-8") || ""
    } catch {
        return ""
    }
}
function writeFile (filePath, data) {
    // 递归创建输出目录
    const parentDir = path.dirname(filePath)
    try {
        fs.mkdirSync(parentDir, { recursive: true })
    } catch {
        return false
    }

    try {
        fs.writeFileSync(filePath, data)
        return true
    } catch {
        return false
    }
}
function copyFile (filePath, repoPath) {
    return new Promise(resolve => {
        // pkg 使用快照文件系统，__dirname, __filename 被劫持了
        // 应使用 process.cwd() 获取执行路径
        const originPath = path.resolve(repoPath, filePath)
        const targetPath = path.resolve(process.cwd(), baseDir, filePath)
        // 递归创建输出目录
        const parentDir = path.dirname(targetPath)
        try {
            fs.mkdirSync(parentDir, { recursive: true })
        } catch {
            resolve("创建导出根目录失败")
        }

        if (isExist(originPath)) {
            fs.copyFile(originPath, targetPath, error => {
                if (error) {
                    console.log(`文件 ${filePath} 提取失败，原因：${err.stack}`)
                    /** todo 输出未成功提取文件 */
                    resolve(`文件 ${filePath} 提取失败，原因：${err.stack}`)
                }
                resolve()
            })
        } else {
            resolve(`文件 ${filePath} 不存在，或已被删除`)
        }
    })
}
function isExist (filePath) {
    try {
        fs.accessSync(filePath)
        return true
    } catch (error) {
        return false
    }
}
FsService.toString = () => '[class FsService]'
module.exports = FsService